package apartado2;

import java.util.LinkedHashSet;
import java.util.Set;

import aima.core.agent.Action;
import aima.core.search.framework.ActionsFunction;
import aima.core.search.framework.ResultFunction;

public class OchoPuzzleFunctionFactory {
	private static ActionsFunction _actionsFunction = null;
	private static ResultFunction _resultFunction = null;

	public static ActionsFunction getActionsFunction() {
		if (null == _actionsFunction) {
			_actionsFunction = new EPActionsFunction();
		}
		return _actionsFunction;
	}

	public static ResultFunction getResultFunction() {
		if (null == _resultFunction) {
			_resultFunction = new EPResultFunction();
		}
		return _resultFunction;
	}

	private static class EPActionsFunction implements ActionsFunction {
		public Set<Action> actions(Object state) {
			OchoPuzzleTablero board = (OchoPuzzleTablero) state;

			Set<Action> actions = new LinkedHashSet<Action>();

			if (board.puedeMueveHueco(OchoPuzzleTablero.ARRIBA)) {
				actions.add(OchoPuzzleTablero.ARRIBA);
			}
			if (board.puedeMueveHueco(OchoPuzzleTablero.ABAJO)) {
				actions.add(OchoPuzzleTablero.ABAJO);
			}
			if (board.puedeMueveHueco(OchoPuzzleTablero.IZQUIERDA)) {
				actions.add(OchoPuzzleTablero.IZQUIERDA);
			}
			if (board.puedeMueveHueco(OchoPuzzleTablero.DERECHA)) {
				actions.add(OchoPuzzleTablero.DERECHA);
			}

			return actions;
		}
	}

	private static class EPResultFunction implements ResultFunction {
		public Object result(Object s, Action a) {
			OchoPuzzleTablero board = (OchoPuzzleTablero) s;

			if (OchoPuzzleTablero.ARRIBA.equals(a)
					&& board.puedeMueveHueco(OchoPuzzleTablero.ARRIBA)) {
				OchoPuzzleTablero newBoard = new OchoPuzzleTablero(board);
				newBoard.mueveHuecoArriba();
				return newBoard;
			} else if (OchoPuzzleTablero.ABAJO.equals(a)
					&& board.puedeMueveHueco(OchoPuzzleTablero.ABAJO)) {
				OchoPuzzleTablero newBoard = new OchoPuzzleTablero(board);
				newBoard.mueveHuecoAbajo();
				return newBoard;
			} else if (OchoPuzzleTablero.IZQUIERDA.equals(a)
					&& board.puedeMueveHueco(OchoPuzzleTablero.IZQUIERDA)) {
				OchoPuzzleTablero newBoard = new OchoPuzzleTablero(board);
				newBoard.mueveHuecoIzquierda();
				return newBoard;
			} else if (OchoPuzzleTablero.DERECHA.equals(a)
					&& board.puedeMueveHueco(OchoPuzzleTablero.DERECHA)) {
				OchoPuzzleTablero newBoard = new OchoPuzzleTablero(board);
				newBoard.mueveHuecoDerecha();
				return newBoard;
			}

			return s;
		}
	}
}
